package com.huilian.netty.coder;

import com.alibaba.fastjson.JSONObject;
import com.google.protobuf.InvalidProtocolBufferException;
import com.huilian.netty.constant.CIMConstant;
import com.huilian.netty.handler.CIMNioSocketAcceptor;
import com.huilian.netty.handler.CIMRequestHandler;
import com.huilian.netty.model.CIMSession;
import com.huilian.netty.model.SocketMessage;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class WebMessageDecoder extends SimpleChannelInboundHandler<Object> {

    private final static String URI = "ws://localhost:%d";

    private static final ConcurrentHashMap<String, WebSocketServerHandshaker> handShakerMap = new ConcurrentHashMap<>();
    public  HashMap<String, CIMRequestHandler> innerHandlerMap = new HashMap<>();
    private static final Logger LOGGER = LoggerFactory.getLogger(WebMessageDecoder.class);
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws InvalidProtocolBufferException {

        if (msg instanceof FullHttpRequest) {
            handleHandshakeRequest(ctx, (FullHttpRequest) msg);
        } else if (msg instanceof WebSocketFrame) {
            handlerWebSocketFrame(ctx, (WebSocketFrame) msg);
        } else {
            log.error("msg type is not support");
        }
    }

    private void handleHandshakeRequest(ChannelHandlerContext ctx, FullHttpRequest req) {

        int port = ((InetSocketAddress) ctx.channel().localAddress()).getPort();

        WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(String.format(URI, port), null, false);

        WebSocketServerHandshaker handShaker = wsFactory.newHandshaker(req);

        handShakerMap.put(ctx.channel().id().asLongText(), handShaker);

        handShaker.handshake(ctx.channel(), req);
    }


    private void handlerWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) throws InvalidProtocolBufferException {

        if (frame instanceof CloseWebSocketFrame) {
            handlerCloseWebSocketFrame(ctx, (CloseWebSocketFrame) frame);
        } else if (frame instanceof PingWebSocketFrame) {
            handlerPingWebSocketFrame(ctx, (PingWebSocketFrame) frame);
        } else {
            handlerBinaryWebSocketFrame(ctx, (TextWebSocketFrame) frame);
        }
    }

    private void handlerCloseWebSocketFrame(ChannelHandlerContext ctx, CloseWebSocketFrame frame) {
        WebSocketServerHandshaker handShaker = handShakerMap.get(ctx.channel().id().asLongText());
        handShaker.close(ctx.channel(), frame.retain());
    }

    private void handlerPingWebSocketFrame(ChannelHandlerContext ctx, PingWebSocketFrame frame) {
        ctx.channel().write(new PongWebSocketFrame(frame.content().retain()));
    }

    private void handlerBinaryWebSocketFrame(ChannelHandlerContext ctx, TextWebSocketFrame textWebSocketFrame) throws InvalidProtocolBufferException {

//        ctx.channel().id().asShortText()

        final String text = textWebSocketFrame.text();
        log.info("读取消息内容：{}", text);
        final SocketMessage socketMessage = JSONObject.parseObject(text, SocketMessage.class);
        ctx.fireChannelRead(socketMessage);
//        ctx.channel().attr(AttributeKey.valueOf(CIMConstant.HEARTBEAT_KEY)).set(System.currentTimeMillis());
////        CIMRequestHandler handler = innerHandlerMap.get(socketMessage.getType());
////        CIMSession session = new CIMSession(ctx.channel());
////        handler.process(session, socketMessage);
//
//        CIMRequestHandler cimRequestHandler = CIMNioSocketAcceptor.innerHandlerMap.get(socketMessage.getType());
//        final CIMSession session = new CIMSession(ctx.channel());
//        if (CIMConstant.MessageType.CLIENT_HEARTBEAT.equalsIgnoreCase(socketMessage.getType())){
//            cimRequestHandler.process(session, socketMessage);
//        } else if (CIMConstant.MessageType.CLIENT_CONNECT_CLOSED.equalsIgnoreCase(socketMessage.getType())){
//
//        } else if (CIMConstant.MessageType.CLIENT_MESSAGE.equalsIgnoreCase(socketMessage.getType())){
//
//        } else if(CIMConstant.MessageType.CLIENT_BIND.equalsIgnoreCase(socketMessage.getType())){
//            cimRequestHandler.process(session, socketMessage);
//        }
//        else {
//
//        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
        LOGGER.warn("Exception caught", cause);
    }
}
